package pruebas;

import modelo.Disparo;
import modelo.Juego;
import modelo.Juego.Modo;
import modelo.Mina;
import modelo.MinaSubmarinaPorContacto;
import modelo.MinaSubmarinaPuntualConRetardo;
import modelo.MinaSubmarinaDobleConRetardo;
import modelo.MinaSubmarinaTripleConRetardo;

import org.junit.Test;
import org.junit.Before;
import org.junit.After;

import excepciones.LaPosicionYaTieneMinaExcepcion;

import junit.framework.TestCase;

public class JuegoTest extends TestCase {
	private Juego juego;
	
	@Before
	public void setUp() throws Exception {
		super.setUp();
		this.juego = new Juego(Modo.PRUEBA);
	}
	
	@After
	public void tearDown() throws Exception {
		super.tearDown();
		this.juego = null;
	}
	
	// Test positivos.
	@Test
    public void testAlPasarTurnoElJuegoNoSeGanoNiSePerdio() {
       	juego.pasarTurno();
    			
    	assertFalse("El juego no se gano",juego.gano());          
   		assertFalse("El juego no se perdio",juego.perdio());
    }
	
	@Test
	public void testPasanLosTurnosYMinaPuedeExplotar() throws LaPosicionYaTieneMinaExcepcion {
		Mina minaTriple = new MinaSubmarinaTripleConRetardo();
		
		juego.seleccionarMina(minaTriple);
		juego.ponerMina(1, 9);						
		juego.pasarTurno();
		juego.pasarTurno();
		juego.pasarTurno();
		
		assertTrue(minaTriple.puedeExplotar());
	}
	
	@Test
	public void testDisparoPuedeExplotar() throws LaPosicionYaTieneMinaExcepcion {
		Mina disparo = new Disparo();
		
		juego.seleccionarMina(disparo);
		juego.ponerMina(1, 8);
		
		assertTrue(disparo.puedeExplotar());
	}

	@Test
	public void testMinaDeContactoPuedeExplotarEn2Turnos() throws LaPosicionYaTieneMinaExcepcion {
		Mina mina = new MinaSubmarinaPorContacto();
		int cantidadDeTurnosQuePasaron = 0;
		
		juego.seleccionarMina(mina);
		juego.ponerMina(4, 1);
		
		while(!mina.puedeExplotar()) {
			juego.pasarTurno();
			cantidadDeTurnosQuePasaron++;
		}
		
		assertTrue(mina.puedeExplotar());
		assertTrue(cantidadDeTurnosQuePasaron == 2);
	}
	
	@Test
	public void testMinaDeContactoPuedeExplotarEn13Turnos() throws LaPosicionYaTieneMinaExcepcion {
		Mina mina=new MinaSubmarinaPorContacto();
		int cantidadDeTurnosQuePasaron = 0;
		
		juego.seleccionarMina(mina);
		juego.ponerMina(3, 0);
		
		while(!mina.puedeExplotar()) {
			juego.pasarTurno();
			cantidadDeTurnosQuePasaron++;
		}
		
		assertTrue(mina.puedeExplotar());
		assertTrue(cantidadDeTurnosQuePasaron == 13);
	}
	
	@Test
	public void testMinaDeContactoPuedeExplotarEn5Turnos() throws LaPosicionYaTieneMinaExcepcion {
		Mina mina=new MinaSubmarinaPorContacto();
		int cantidadDeTurnosQuePasaron = 4;
		
		juego.seleccionarMina(mina);
		juego.pasarTurno();
		juego.pasarTurno();
		juego.pasarTurno();
		juego.pasarTurno();	
		juego.ponerMina(1, 3);
		
		while(!mina.puedeExplotar()) {
			juego.pasarTurno();
			cantidadDeTurnosQuePasaron++;
		}
		
		assertTrue(cantidadDeTurnosQuePasaron==5);
		assertTrue(mina.puedeExplotar());
	}
	
	@Test
	public void testJugadorGana() throws LaPosicionYaTieneMinaExcepcion{
		juego.pasarTurno();

		Mina mina = new MinaSubmarinaTripleConRetardo();
		juego.seleccionarMina(mina);
		juego.ponerMina(4, 3);
		
		Mina mina2 = new MinaSubmarinaTripleConRetardo();
		juego.seleccionarMina(mina2);
		juego.ponerMina(2, 7);
		
		Mina disparo4 = new Disparo();
		juego.seleccionarMina(disparo4);
		juego.ponerMina(6, 3);
		
		Mina disparo3 = new Disparo();
		juego.seleccionarMina(disparo3);
		juego.ponerMina(6, 4);
		
		Mina disparo6 = new Disparo();
		juego.seleccionarMina(disparo6);
		juego.ponerMina(6, 5);
		
		Mina disparo7 = new Disparo();
		juego.seleccionarMina(disparo7);
		juego.ponerMina(4, 5);
		
		Mina disparo8 = new Disparo();
		juego.seleccionarMina(disparo8);
		juego.ponerMina(6, 2);
		
		Mina disparo9 = new Disparo();
		juego.seleccionarMina(disparo9);
		juego.ponerMina(5, 5);
		
		juego.pasarTurno();
		juego.pasarTurno();
		juego.pasarTurno();

		Mina mina3=new MinaSubmarinaTripleConRetardo();
		juego.seleccionarMina(mina3);
		juego.ponerMina(2, 3);
		
		Mina disparo2=new Disparo();
		juego.seleccionarMina(disparo2);
		juego.ponerMina(0, 2);

		// Antes de pasar de turno, antes de mover los barcos, las minas que pueden explotar, explotan.
		juego.pasarTurno();
		juego.pasarTurno();
		juego.pasarTurno();
		juego.pasarTurno();

		Mina disparo10 = new Disparo();
		juego.seleccionarMina(disparo10);
		juego.ponerMina(7, 7);
		
		Mina disparo11 = new Disparo();
		juego.seleccionarMina(disparo11);
		juego.ponerMina(6,  7);
		
		Mina disparo12 = new Disparo();
		juego.seleccionarMina(disparo12);
		juego.ponerMina(5, 7);
		
		Mina disparo13 = new Disparo();
		juego.seleccionarMina(disparo13);
		juego.ponerMina(6, 5);
		
		juego.pasarTurno();
		juego.pasarTurno();
		
		assertTrue(juego.gano());
	}
	
	// Test negativos.
	@Test
	public void testJugadorPierde(){
		do{
			Mina mina=new Disparo();
			juego.seleccionarMina(mina);
			try {
				juego.ponerMina(5, 5);
			} catch (LaPosicionYaTieneMinaExcepcion e) {}
			juego.pasarTurno();
		}while(!juego.perdio());
		
		assertTrue(juego.perdio());
	}
	
	@Test
	public void testPasanMenosDeTresTurnosYLaMinaPuntualNoPuedeExplotar() throws LaPosicionYaTieneMinaExcepcion {
		Mina minaPuntual = new MinaSubmarinaPuntualConRetardo();
		
		juego.seleccionarMina(minaPuntual);
		juego.ponerMina(5, 5);						
		juego.pasarTurno();
		juego.pasarTurno();
		
		assertFalse(minaPuntual.puedeExplotar());
	}
	
	@Test
	public void testPasanMenosDeTresTurnosYLaMinaDobleNoPuedeExplotar() throws LaPosicionYaTieneMinaExcepcion {
		Mina minaDoble = new MinaSubmarinaDobleConRetardo();
		
		juego.seleccionarMina(minaDoble);
		juego.ponerMina(8, 8);
		juego.pasarTurno();
		juego.pasarTurno();
		
		assertFalse(minaDoble.puedeExplotar());
	}
	
	@Test
	public void testPasanMenosDeTresTurnosYLaMinaTripleNoPuedeExplotar() throws LaPosicionYaTieneMinaExcepcion {
		Mina minaTriple = new MinaSubmarinaTripleConRetardo();
		
		juego.seleccionarMina(minaTriple);
		juego.ponerMina(3, 3);						
		juego.pasarTurno();
		juego.pasarTurno();
		
		assertFalse(minaTriple.puedeExplotar());
	}
}
